﻿using System.Collections.Generic;
using NUnit.Framework;
using Novice.Tools;

namespace Novice.Tools.Test
{
    internal class Node
    {
        public string Name { get; set; }
        public IEnumerable<Node> Items { get; set; }
    }

    internal static class NodeExtensions
    {
        public static IEnumerable<Node> Flatten(this Node node, TreeEnumerationStrategy enumerationStrategy = TreeEnumerationStrategy.RootFirst)
        {
            return EnumTree.FlattenSingleItem(node, a => a.Items, enumerationStrategy);
        }
    }

    [TestFixture]
    public class TestEnumeration
    {
        #region data

        private readonly Node _topNode = new Node
                                         {
                                             Name = "Top level",
                                             Items = new List<Node>
                                                     {
                                                         new Node
                                                         {
                                                             Name = "first",
                                                             Items = new List<Node>
                                                                     {
                                                                         new Node
                                                                         {
                                                                             Name = "second",
                                                                             Items = new List<Node>()
                                                                         },
                                                                         new Node
                                                                         {
                                                                             Name = "second",
                                                                             Items = new List<Node>()
                                                                         },
                                                                         new Node
                                                                         {
                                                                             Name = "second"
                                                                         }
                                                                     }
                                                         },
                                                         new Node
                                                         {
                                                             Name = "first",
                                                             Items = new List<Node>
                                                                     {
                                                                         new Node
                                                                         {
                                                                             Name = "second"
                                                                         },
                                                                         new Node
                                                                         {
                                                                             Name = "second"
                                                                         },
                                                                         new Node
                                                                         {
                                                                             Name = "second",
                                                                             Items = new List<Node>()
                                                                         }
                                                                     }
                                                         },
                                                         new Node
                                                         {
                                                             Name = "first",
                                                             Items = new List<Node>
                                                                     {
                                                                         new Node
                                                                         {
                                                                             Name = "second"
                                                                         },
                                                                         new Node
                                                                         {
                                                                             Name = "second"
                                                                         },
                                                                         new Node
                                                                         {
                                                                             Name = "second"
                                                                         }
                                                                     }
                                                         }
                                                     }
                                         };

        private readonly List<string> _rootLastOrder = new List<string>
                                                    {
                                                        "second",
                                                        "second",
                                                        "second",
                                                        "first",
                                                        "second",
                                                        "second",
                                                        "second",
                                                        "first",
                                                        "second",
                                                        "second",
                                                        "second",
                                                        "first",
                                                        "Top level"
                                                    };

        private readonly List<string> _rootFirstOrder = new List<string>
                                                    {
                                                        "Top level",
                                                        "first",
                                                        "second",
                                                        "second",
                                                        "second",
                                                        "first",
                                                        "second",
                                                        "second",
                                                        "second",
                                                        "first",
                                                        "second",
                                                        "second",
                                                        "second"
                                                    };
        #endregion

        [Test]
        public void RootLastEnumeration()
        {
            using (var testEnum = _topNode.Flatten(TreeEnumerationStrategy.RootLast).GetEnumerator())
            using (var checkEnum = _rootLastOrder.GetEnumerator())
            {
                while (checkEnum.MoveNext())
                {
                    testEnum.MoveNext();
                    var expected = checkEnum.Current;
                    var original = testEnum.Current.Name;
                    Assert.AreEqual(expected, original);
                }
            }
        }

        [Test]
        public void RootFirstEnumeration()
        {
            using (var testEnum = _topNode.Flatten(TreeEnumerationStrategy.RootFirst).GetEnumerator())
            using (var checkEnum = _rootFirstOrder.GetEnumerator())
            {
                while (checkEnum.MoveNext())
                {
                    testEnum.MoveNext();
                    var expected = checkEnum.Current;
                    var original = testEnum.Current.Name;
                    Assert.AreEqual(expected, original);
                }
            }
        }
    }
}
